/*!
 * \file es_core.c
 *
 * \brief es 解析模块
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * ct管理用共通函数
 *
 * \version 4.0
 * \author geyh
 * \date 2016/08/29
 *
 */

#include <stdio.h>
#include <sys/time.h>

#include "frsutl.h"
#include "frservice_comm.h"
#include "conntrack.h"
#include "module.h"
#include "frct_comm.h"
#include "es_core.h"
#include "frreport_comm.h"
#include "config.h"

extern void *g_p_apm_context;

/* 4位小头节序转到本地字节序 */
#define pntohi(p)  ((unsigned int)*((const unsigned char *)(p + 0)) << 24 | \
                    (unsigned int)*((const unsigned char *)(p + 1)) << 16 | \
                    (unsigned int)*((const unsigned char *)(p + 2)) << 8 | \
                    (unsigned int)*((const unsigned char *)(p + 3)) << 0)


/*!
 * es 私有数据创建
 *
 * \param void
 *
 * \return
 *
 */
es_private* __es_private_create(void)
{
    es_private *p_st_private = NULL;

    p_st_private = (es_private *)frmalloc(sizeof(es_private));
    if(p_st_private == NULL)
        return NULL;

    memset(p_st_private, 0x00, sizeof(es_private));

    return p_st_private;

}


/*!
 * 判断是否是es协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet   (输入数据)
 *
 * \return APM_L7_IS_YES   属于es协议\n
 *         APM_L7_IS_NO   不属于es协议
 *
 * \note
 *
 */
int es_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    char *p_pos = NULL;
    unsigned int ui_len = 0;
    int i_ret = 0;

    if (p_st_conn == NULL || p_st_packet == NULL ||
        p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len < 6)
        return APM_L7_IS_NO;

    //长度为6  malformed packet
    if(p_st_packet->ui_payload_len == 6)
    {
        if (memcmp(p_st_packet->p_payload, "\x45\x53\xff\xff\xff\xff", 6) == 0)
        {
            if(frct_get_direct_known(p_st_conn) == FR_DIRECT_KNOWN)
                return APM_L7_IS_YES;
        }

        //方向不确定时返回
        goto UNKNOW;
    }

    if(p_st_packet->ui_payload_len < 19)
        goto UNKNOW;

    p_pos = p_st_packet->p_payload;

    if(memcmp(p_pos, "\x45\x53", 2)!= 0)
        goto UNKNOW;
    p_pos += 2;

    //长度 指长度位之后的数据总长度
    ui_len = pntohi(p_pos);
    p_pos += 4;

    if(ui_len < p_st_packet->ui_payload_len - 6)
        goto UNKNOW;

    //request/response id
    p_pos += 8;

    //flag
    if(p_pos[0] > '\x07')
        return APM_L7_IS_NO;

    if(frct_get_direct_known(p_st_conn) == FR_DIRECT_KNOWN)
    {
        if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        else
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);

        return APM_L7_IS_YES;
    }

    //response
    if(p_pos[0] & ES_FLAG_RES)
    {
        frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);
    }
    else
    {
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
        frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
    }

    return APM_L7_IS_YES;

UNKNOW:

    if(frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if(i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if(i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if(i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if(i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }

    return APM_L7_IS_NO;

}

/*!
 * es 获取操作信息
 *
 * \p_st_packet                      (数据包信息)
 *
 * \return 操作信息
 *
 */
FR_STATIC char * __es_get_action(Frbyte_Packet *p_st_packet)
{
    uint8_t u8_len = 0;
    char *p_action = NULL;
    int i_ret = 0;

    i_ret = bytebuff_get_char(p_st_packet, &u8_len);
    if(i_ret == FR_FAIL)
        return NULL;

    p_action = (char *)frmalloc(u8_len + 1);
    if(p_action == NULL)
        return NULL;

    i_ret = bytebuff_get_bytes(p_st_packet, p_action, u8_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_action);
        return NULL;
    }

    p_action[u8_len] = '\0';
    return p_action;

}

/*!
 * es request 操作信息解析
 *
 * \p_st_packet                      (数据包信息)
 * \p_st_pritate                     (es 私有数据)
 * \p_st_report_body                 (es 上班信息收集)
 * \p_st_hash_report                 (数据上报hash)
 *
 * \return                          APM_L7_ANALYZE_FAIL     (失败)
 *                                  APM_L7_ANALYZE_TODO     (数据包未完整)
 *                                  APM_L7_ANALYZE_SUCC     (成功)
 *
 */
FR_STATIC int __es_request(Frbyte_Packet *p_st_packet, es_private *p_st_pritate, Frreport_body_data *p_st_report_body, Frhash_header *p_st_hash_report)
{
    int i_ret = 0;
    uint8_t u8_flag = 0;
    uint32_t u32_version = 0;
    uint8_t u8_flag_compress = 0;
    char *p_action = NULL;
    char *p_data = NULL;
    int i_remain_len = 0;

    if(p_st_packet == NULL || p_st_pritate == NULL || p_st_report_body == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    //id
    i_ret = bytebuff_get_long(p_st_packet, 8, &p_st_pritate->u64_request_id, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //status
    i_ret = bytebuff_get_char(p_st_packet, &u8_flag);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //request  确认
    if(u8_flag & ES_FLAG_RES)
        return FR_FAIL;

    //version
    i_ret = bytebuff_get_int(p_st_packet, 4, &u32_version, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;


    u8_flag_compress = (uint8_t)(u8_flag & ES_FLAG_COMPRESS);
    if(u8_flag_compress)
    {
        //todo 跳过8个字节？
        i_ret = bytebuff_skip(p_st_packet, 8);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //Action
    p_action = __es_get_action(p_st_packet);
    if(p_action == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret = frreport_body_l7_add_str(p_st_report_body, APM_REPORT_KEY_TRANS_TITLE, p_action);
    if(i_ret == FR_FAIL)
    {
        frfree(p_action);
        return APM_L7_ANALYZE_FAIL;
    }
    frfree(p_action);

    i_remain_len = bytebuff_remaining(p_st_packet);
    if(i_remain_len == 0)
        return APM_L7_ANALYZE_SUCC;

    p_data = (char *)frmalloc((unsigned int)i_remain_len + 1);
    if(p_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret = bytebuff_get_bytes(p_st_packet, p_data, (unsigned int)i_remain_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_data);
        return APM_L7_ANALYZE_FAIL;
    }

    i_ret = frreport_body_l7_add_bin(p_st_report_body, "request.es.data", p_data, (unsigned int)i_remain_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_data);
        return APM_L7_ANALYZE_FAIL;
    }

    frfree(p_data);
    return APM_L7_ANALYZE_SUCC;
}

/*!
 * es response 操作信息解析
 *
 * \p_st_packet                      (数据包信息)
 * \p_st_pritate                     (es 私有数据)
 * \p_st_report_body                 (es 上班信息收集)
 * \p_st_hash_report                 (数据上报hash)
 *
 * \return                          APM_L7_ANALYZE_FAIL     (失败)
 *                                  APM_L7_ANALYZE_TODO     (数据包未完整)
 *                                  APM_L7_ANALYZE_SUCC     (成功)
 *
 */
FR_STATIC int __es_response(Frbyte_Packet *p_st_packet, es_private *p_st_pritate, Frreport_body_data *p_st_report_body, Frhash_header *p_st_hash_report)
{
    int i_ret = 0;
    uint8_t u8_flag = 0;
    uint32_t u32_version = 0;
    char *p_data = NULL;
    int i_remain_len = 0;
    uint64_t u64_request_id = 0;

    if(p_st_packet == NULL || p_st_pritate == NULL || p_st_report_body == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    //id
    i_ret = bytebuff_get_long(p_st_packet, 8, &u64_request_id, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL || u64_request_id != p_st_pritate->u64_request_id)
        return APM_L7_ANALYZE_FAIL;

    //status
    i_ret = bytebuff_get_char(p_st_packet, &u8_flag);
    if(i_ret == FR_FAIL)
        return FR_FAIL;

    //response  确认
    if(!(u8_flag & ES_FLAG_RES))
        return FR_FAIL;

    //response code
    if(u8_flag & ES_FLAG_ERR)
    {
        i_ret = frreport_body_l7_add_long(p_st_report_body, APM_REPORT_KEY_RESP_CODE, 1);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        i_ret = frreport_body_l7_add_long(p_st_report_body, APM_REPORT_KEY_RESP_CODE, 0);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
    }

    //version
    i_ret = bytebuff_get_int(p_st_packet, 4, &u32_version, BYTE_BIG_ENDIAN);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    //data
    i_remain_len = bytebuff_remaining(p_st_packet);
    if(i_remain_len == 0)
        return APM_L7_ANALYZE_SUCC;

    p_data = (char *)frmalloc((unsigned int)i_remain_len + 1);
    if(p_data == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret = bytebuff_get_bytes(p_st_packet, p_data, (unsigned int)i_remain_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_data);
        return APM_L7_ANALYZE_FAIL;
    }

    i_ret = frreport_body_l7_add_bin(p_st_report_body, "response.es.data", p_data, (unsigned int)i_remain_len);
    if(i_ret == FR_FAIL)
    {
        frfree(p_data);
        return APM_L7_ANALYZE_FAIL;
    }

    frfree(p_data);
    return APM_L7_ANALYZE_SUCC;
}


/*!
 * es request 解析
 *
 * \p_st_packet                      (数据包信息)
 * \p_st_session                     (session 信息)
 * \p_st_conn                        (connect 信息)
 * \p_st_hash_report                 (数据上报hash)
 *
 * \return                          APM_L7_ANALYZE_FAIL     (失败)
 *                                  APM_L7_ANALYZE_TODO     (数据包未完整)
 *                                  APM_L7_ANALYZE_SUCC     (成功)
 *
 */
int es_request(Apm_packet *p_st_packet, L7_session *p_st_session, Conntrack *p_st_conn, Frhash_header *p_st_hash_report)
{
    int i_ret = 0;
    es_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    Frreport_data *p_st_report_data = NULL;
    Frbyte_Packet *p_st_data = NULL;
    char arr_es[3];
    unsigned long ul_tmp = 0;

    if(p_st_packet == NULL || p_st_session == NULL || p_st_conn == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (es_private *)frct_get_session_private(p_st_session);
    if(p_st_private == NULL)
    {
        p_st_private = __es_private_create();
        if(p_st_private == NULL)
            return APM_L7_ANALYZE_FAIL;
        p_st_session->p_session_private = p_st_private;
    }

    p_st_l4_trans = &p_st_private->st_l4_trans;

    if(p_st_private->p_st_data == NULL)
    {
        p_st_private->p_st_data = bytebuff_creat();
        if(p_st_private->p_st_data == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    p_st_data = p_st_private->p_st_data;

    //首包时间
    if(p_st_l4_trans->st_request_time_first_byte.tv_sec == 0)
    {
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
    }

    //字节数
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    i_ret = bytebuff_add(p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    if(p_st_private->ui_data_len == 0)
    {
        //ES 开头
        i_ret = bytebuff_get_bytes(p_st_data, arr_es, 2);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_TODO;

        if(memcmp(arr_es, "ES", 2) != 0)
            return APM_L7_ANALYZE_FAIL;

        //长度
        i_ret = bytebuff_get_int(p_st_data, 4, &p_st_private->ui_data_len, BYTE_BIG_ENDIAN);
        if(i_ret == FR_FAIL)
        {
            bytebuff_rewind(p_st_data);
            return APM_L7_ANALYZE_TODO;
        }

        if(p_st_private->ui_data_len == 0xffffffff)
            return APM_L7_ANALYZE_SUCC;
        else if(p_st_private->ui_data_len > 0x7fffffff)
            return APM_L7_ANALYZE_FAIL;

    }

    //取得所有数据
    if(p_st_private->ui_data_len > (unsigned int)bytebuff_remaining(p_st_data))
        return APM_L7_ANALYZE_TODO;

    p_st_report_body = frreport_body_new_l7(p_st_conn);
    if(p_st_report_body == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret = __es_request(p_st_data, p_st_private, p_st_report_body, p_st_hash_report);
    if(i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;
    
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    i_ret = frreport_body_l7_add_connInfo(p_st_report_body, p_st_conn);
    if(i_ret == FR_FAIL)
        goto ERROR;

    //seq ++
    p_st_private->ul_seq = frct_seq_increase(p_st_conn);
    if(frreport_body_l7_add_ulong(p_st_report_body, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //ResponseRequired
    if(frreport_body_l7_add_int(p_st_report_body, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
        goto ERROR;

    //start time
    if(frreport_body_l7_add_timeval(p_st_report_body, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //send_time_us
    ul_tmp = (unsigned long)frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &p_st_l4_trans->st_request_time);
    if(frreport_body_l7_add_ulong(p_st_report_body, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if(frreport_body_l7_add_long(p_st_report_body, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    if(frreport_body_l7_add_timeval(p_st_report_body, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_private->p_lst_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_report_body);
    p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_report_body);

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if(p_st_report_data == NULL)
        goto ERROR;

    if(frreport_data_add_body(p_st_report_data, p_st_report_body) == FR_FAIL)
        goto ERROR;

    if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;

    //私有数据初始化
    p_st_private->ui_data_len = 0;
    bytebuff_free(&p_st_private->p_st_data);

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);
    
ERROR:

    if(p_st_report_body)
        frreport_body_free(&p_st_report_body);

    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    return APM_L7_ANALYZE_FAIL;

}

/*!
 * es response 解析
 *
 * \p_st_packet                      (数据包信息)
 * \p_st_session                     (session 信息)
 * \p_st_conn                        (connect 信息)
 * \p_st_hash_report                 (数据上报hash)
 *
 * \return                          APM_L7_ANALYZE_FAIL     (失败)
 *                                  APM_L7_ANALYZE_TODO     (数据包未完整)
 *                                  APM_L7_ANALYZE_SUCC     (成功)
 *
 */
int es_response(Apm_packet *p_st_packet, L7_session *p_st_session, Conntrack *p_st_conn, Frhash_header *p_st_hash_report)
{
    int i_ret = 0;
    es_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_body_data *p_st_report_body = NULL;
    Frreport_data *p_st_report_data = NULL;
    Frbyte_Packet *p_st_data = NULL;
    char arr_es[3];
    unsigned long ul_tmp = 0;

    if(p_st_packet == NULL || p_st_session == NULL || p_st_conn == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (es_private *)frct_get_session_private(p_st_session);
    if(p_st_private == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_l4_trans = &p_st_private->st_l4_trans;

    if(p_st_private->p_st_data == NULL)
    {
        p_st_private->p_st_data = bytebuff_creat();
        if(p_st_private->p_st_data == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    p_st_data = p_st_private->p_st_data;

    //首包时间
    if(p_st_l4_trans->st_response_time_first_byte.tv_sec == 0)
    {
        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
    }

    //字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    i_ret = bytebuff_add(p_st_data, p_st_packet->p_payload, p_st_packet->ui_payload_len);
    if(i_ret == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

    if(p_st_private->ui_data_len == 0)
    {
        //ES 开头
        i_ret = bytebuff_get_bytes(p_st_data, arr_es, 2);
        if(i_ret == FR_FAIL)
            return APM_L7_ANALYZE_TODO;

        if(memcmp(arr_es, "ES", 2) != 0)
            return APM_L7_ANALYZE_FAIL;

        //长度
        i_ret = bytebuff_get_int(p_st_data, 4, &p_st_private->ui_data_len, BYTE_BIG_ENDIAN);
        if(i_ret == FR_FAIL)
        {
            bytebuff_rewind(p_st_data);
            return APM_L7_ANALYZE_TODO;
        }

        if(p_st_private->ui_data_len == 0xffffffff)
            return APM_L7_ANALYZE_SUCC;
        else if(p_st_private->ui_data_len > 0x7fffffff)
            return APM_L7_ANALYZE_FAIL;

    }

    //取得所有数据
    if(p_st_private->ui_data_len > (unsigned int)bytebuff_remaining(p_st_data))
        return APM_L7_ANALYZE_TODO;

    p_st_report_body = frreport_body_new_l7(p_st_conn);
    if(p_st_report_body == NULL)
        return APM_L7_ANALYZE_FAIL;

    i_ret = __es_response(p_st_data, p_st_private, p_st_report_body, p_st_hash_report);
    if(i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    //start time
    if(frreport_body_l7_add_timeval(p_st_report_body, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    //send_time_us
    ul_tmp = (unsigned long)frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &p_st_l4_trans->st_response_time);
    if(frreport_body_l7_add_ulong(p_st_report_body, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if(frreport_body_l7_add_long(p_st_report_body, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    if(frreport_body_l7_add_timeval(p_st_report_body, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    FRREPORT_BODY_L7LIST_SET_REQ(p_st_report_body, &p_st_private->p_lst_req);
    FRREPORT_BODY_L7LIST_SET_COMM(p_st_report_body, &p_st_private->p_lst_comm);

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if(p_st_report_data == NULL)
        goto ERROR;

    if(frreport_data_add_body(p_st_report_data, p_st_report_body) == FR_FAIL)
        goto ERROR;

    if(frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;

    //私有数据初始化
    p_st_private->ui_data_len = 0;
    bytebuff_free(&p_st_private->p_st_data);
    frreport_body_l7list_free(&p_st_private->p_lst_req);
    frreport_body_l7list_free(&p_st_private->p_lst_comm);

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:

    if(p_st_report_body)
        frreport_body_free(&p_st_report_body);

    if(p_st_report_data)
        frreport_data_free(&p_st_report_data);

    return APM_L7_ANALYZE_FAIL;

}


/*!
 * es response 解析
 *
 * \p_st_conn                        (connect 信息)
 * \p_st_packet                      (数据包信息)
 * \p_st_hash_report                 (数据上报hash)
 *
 * \return                          APM_L7_ANALYZE_FAIL     (失败)
 *                                  APM_L7_ANALYZE_TODO     (数据包未完整)
 *                                  APM_L7_ANALYZE_SUCC     (成功)
 *
 */
int es_analysis(Conntrack *p_st_conn, Apm_packet *p_st_packet, Frhash_header *p_st_hash_report)
{
    int i_ret = 0;
    L7_session *p_st_session = NULL;

    if(p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin syn 包  销毁私有数据
    if(p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        //文件上传数据上报
        es_session_destroy(p_st_session->p_session_private);
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //request
    if(p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = es_request(p_st_packet, p_st_session,p_st_conn, p_st_hash_report);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = es_response(p_st_packet, p_st_session,p_st_conn, p_st_hash_report);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:

    if(p_st_session->p_session_private)
        es_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;


}

/*!
 * es session 信息销毁
 *
 * \p_private_session                        (es session 信息销毁)
 *
 * \return                          FR_SUCC (成功)
 *
 */
int es_session_destroy(void *p_private_session)
{
    es_private *p_st_private = (es_private *)p_private_session;

    if(p_st_private)
    {
        if(p_st_private->p_st_data)
            bytebuff_free(&p_st_private->p_st_data);

        if(p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if(p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        frfree(p_st_private);
    }

    return FR_SUCC;
}

